package com.xie.leetcode.list;

//2. 两数相加
//        给你两个 非空 的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储 一位 数字。
//
//        请你将两个数相加，并以相同形式返回一个表示和的链表。
//
//        你可以假设除了数字 0 之外，这两个数都不会以 0 开头。
//
//
//
//        示例 1：
//
//
//        输入：l1 = [2,4,3], l2 = [5,6,4]
//        输出：[7,0,8]
//        解释：342 + 465 = 807.
//        示例 2：
//
//        输入：l1 = [0], l2 = [0]
//        输出：[0]
//        示例 3：
//
//        输入：l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
//        输出：[8,9,9,9,0,0,0,1]
//
//
//        提示：
//
//        每个链表中的节点数在范围 [1, 100] 内
//        0 <= Node.val <= 9
//        题目数据保证列表表示的数字不含前导零

import com.xie.leetcode.base.ListNode;

import java.math.BigDecimal;

/**
 * @author xiezhendong
 * @date 2021/10/25
 */
public class AddTwoNumbers {

    public static void main(String[] args) {
        AddTwoNumbers addTwoNumbers = new AddTwoNumbers();
        ListNode l1_3 = new ListNode(3, null);
        ListNode l1_4 = new ListNode(4, l1_3);
        ListNode l1_2 = new ListNode(2, l1_4);
        ListNode l2_4 = new ListNode(4, null);
        ListNode l2_6 = new ListNode(6, l2_4);
        ListNode l2_5 = new ListNode(5, l2_6);

        System.out.println(addTwoNumbers.addTwoNumbers(l1_2, l2_5));


        ListNode l3_11 = new ListNode(1, null);
        ListNode l3_10 = new ListNode(1, l3_11);
        ListNode l3_9 = new ListNode(1, l3_10);
        ListNode l3_8 = new ListNode(1, l3_9);
        ListNode l3_7 = new ListNode(1, l3_8);
        ListNode l3_6 = new ListNode(1, l3_7);
        ListNode l3_5 = new ListNode(1, l3_6);
        ListNode l3_4 = new ListNode(1, l3_5);
        ListNode l3_3 = new ListNode(1, l3_4);
        ListNode l3_2 = new ListNode(1, l3_3);
        ListNode l3_1 = new ListNode(1, l3_2);

        System.out.println(addTwoNumbers.addTwoNumbers(l3_1, l3_1));

    }

    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1.next == null
                && l2.next == null
                && (l1.val + l2.val) < 10) {
            return new ListNode(l1.val + l2.val);
        }

        int valNew;
        int jinWeiNumNew;
        int num = l1.val + l2.val;
        if (num < 10) {
            valNew = num;
            jinWeiNumNew = 0;
        } else {
            valNew = num - 10;
            jinWeiNumNew = ((num - valNew) / 10);
        }
        return new ListNode(valNew, addNode(l1.next, l2.next, jinWeiNumNew));
    }

    private ListNode addNode(ListNode next1, ListNode next2, int jinWeiNum) {
        if (next1 == null && next2 == null && jinWeiNum == 0) {
            return null;
        }
        if (next1 == null && next2 == null) {
            return new ListNode(jinWeiNum);
        }

        int valNew;
        int jinWeiNumNew;
        int num = (next1 == null ? 0 : next1.val) + (next2 == null ? 0 : next2.val) + jinWeiNum;
        if (num < 10) {
            valNew = num;
            jinWeiNumNew = 0;
        } else {
            valNew = num - 10;
            jinWeiNumNew = ((num - valNew) / 10);
        }
        if (next1 == null) {
            return new ListNode(valNew, addNode(null, next2.next, jinWeiNumNew));
        } else if (next2 == null) {
            return new ListNode(valNew, addNode(next1.next, null, jinWeiNumNew));
        } else {
            return new ListNode(valNew, addNode(next1.next, next2.next, jinWeiNumNew));
        }
    }

    /**
     * 算出值后重新设置
     *
     * @param l1
     * @param l2
     * @return
     */
    public ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
        int len1 = getLen(l1);
        BigDecimal l1Value = getValue(l1, len1);
        int len2 = getLen(l2);
        BigDecimal l2Value = getValue(l2, len2);
        BigDecimal lValue = l1Value.add(l2Value);
        return getListNode(lValue);
    }

    private int getLen(ListNode node) {
        if (node.next == null) {
            return 1;
        }
        return getLen(node.next) + 1;
    }

    private ListNode getListNode(BigDecimal lValue) {
        if ((lValue.divide(BigDecimal.TEN)).compareTo(BigDecimal.ONE) == -1) {
            return new ListNode(lValue.intValue());
        }
        BigDecimal nodeValue = lValue.subtract(BigDecimal.valueOf(lValue.divide(BigDecimal.TEN).intValue()).multiply(BigDecimal.TEN));
        ListNode next = getListNode(lValue.divide(BigDecimal.TEN));
        return new ListNode(nodeValue.intValue(), next);
    }

    private BigDecimal getValue(ListNode node, int len) {
        BigDecimal nodeValue = BigDecimal.valueOf(node.val);
        if (node.next == null) {
            return nodeValue;
        }
        BigDecimal nextValue = getValue(node.next, len - 1);
        nodeValue = nodeValue.add(nextValue.multiply(BigDecimal.TEN));
        return nodeValue;
    }
}
